import crypto from 'crypto';
import { Logger, AppError, ErrorCode } from '../utils/logger';

// 668Pay配置接口
export interface Pay668Config {
  mchNo: string;
  appId: string;
  apiKey: string;
  apiUrl: string;
  notifyUrl?: string;
}

// 创建订单请求参数
export interface CreatePay668OrderRequest {
  userId: number;
  amount: number;
  paymentMethod: 'BankTransfer' | 'qrPay';
  orderId: string;
  transAccNo: string; // 银行卡号（必填）
  paymentName: string; // 付款人真实名称（必填）
  bankCode: string; // 银行编码（必填）
  customerEmail?: string; // 客户邮箱
  customerPhone?: string; // 客户手机号
  extendParam?: string; // 透传参数
}

// 创建提现订单请求参数
export interface CreatePay668PayoutRequest {
  amount: number;
  paymentMethod: 'BankTransfer' | 'qrPay';
  orderId: string;
  receiverName: string; // 收款人姓名（必填）
  receiverBankCard: string; // 收款银行卡号（必填）
  bankCode: string; // 银行编码（必填）
  customerEmail?: string; // 客户邮箱
  customerPhone?: string; // 客户手机号
  remark?: string; // 支付备注
}

// 668Pay API响应
export interface Pay668Response {
  code: number;
  msg?: string;
  sign?: string;
  data?: {
    payOrderId: string;
    mchOrderNo: string;
    orderState: number;
    payDataType: string;
    payData?: string;
    errCode?: string;
    errMsg?: string;
  };
}

// 668Pay代付API响应
export interface Pay668PayoutResponse {
  code: number;
  msg?: string;
  sign?: string;
  data?: {
    transferId: string; // 转账订单号
    mchOrderNo: string; // 商户转账单号
    amount: number; // 到账金额（分）
    mchFeeAmount: number; // 转账手续费（分）
    amountTo: number; // 交易总金额（分）
    accountNo: string; // 收款账号
    accountName: string; // 收款人姓名
    state: number; // 转账状态：0订单生成,1转账中,2转账成功,3转账失败,4转账关闭
    errCode?: string; // 渠道错误码
    errMsg?: string; // 渠道错误描述
  };
}

// 668Pay查询订单请求参数
export interface QueryPay668OrderRequest {
  payOrderId?: string; // 支付订单号，与mchOrderNo二者传一即可
  mchOrderNo?: string; // 商户订单号，与payOrderId二者传一即可
}

// 668Pay查询订单响应
export interface Pay668QueryResponse {
  code: number;
  msg?: string;
  sign?: string;
  data?: {
    payOrderId: string;
    mchNo: string;
    appId: string;
    mchOrderNo: string;
    amount: number;
    currency: string;
    state: number; // 1: 支付中, 2: 支付成功, 3: 支付失败, 6: 订单关闭, 7: 订单待结算
    errCode?: string;
    errMsg?: string;
    extParam?: string;
    createdAt: number;
    successTime?: number;
  };
}

// 668Pay异步通知数据
export interface Pay668Notification {
  payOrderId: string;
  mchOrderNo: string;
  orderState: number;
  amount: string;
  customerName: string;
  customerEmail: string;
  customerPhone: string;
  wayCode?: string;
  extParam?: string;
  sign: string;
}

export class Pay668Service {
  private config: Pay668Config;

  constructor(config: Pay668Config) {
    this.config = config;
  }

  /**
   * MD5签名
   */
  private signWithMD5(data: Record<string, any>): string {
    try {
      Logger.debug('开始生成668Pay签名', { dataKeys: Object.keys(data) });

      // 过滤空值参数
      const filteredData: Record<string, string> = {};
      Object.keys(data).forEach(key => {
        if (data[key] !== null && data[key] !== undefined && data[key] !== '') {
          filteredData[key] = String(data[key]);
        }
      });

      // 按ASCII码排序
      const sortedKeys = Object.keys(filteredData).sort();
      
      // 拼接字符串
      const stringA = sortedKeys.map(key => `${key}=${filteredData[key]}`).join('&');
      
      // 添加密钥
      const stringSignTemp = `${stringA}&key=${this.config.apiKey}`;
      
      Logger.debug('668Pay签名字符串', { stringSignTemp: stringSignTemp.replace(this.config.apiKey, '***') });
      
      // MD5加密并转大写
      const signature = crypto.createHash('md5').update(stringSignTemp, 'utf8').digest('hex').toUpperCase();
      
      Logger.debug('668Pay签名生成成功', { signatureLength: signature.length });
      
      return signature;
    } catch (error) {
      Logger.error('668Pay签名生成失败', error);
      throw new AppError(`668Pay签名失败: ${error instanceof Error ? error.message : 'Unknown error'}`, ErrorCode.PAYMENT_SIGN_ERROR);
    }
  }

  /**
   * 验证668Pay签名
   */
  verifySignature(data: Record<string, any>, signature: string): boolean {
    try {
      const { sign, ...params } = data;
      const calculatedSign = this.signWithMD5(params);
      const isValid = calculatedSign === signature;
      
      Logger.debug('668Pay签名验证', {
        isValid,
        receivedSign: signature,
        calculatedSign
      });
      
      return isValid;
    } catch (error) {
      Logger.error('668Pay签名验证失败', error);
      return false;
    }
  }

  /**
   * 验证创建订单请求参数
   */
  private validateCreateOrderRequest(request: CreatePay668OrderRequest): void {
    Logger.debug('开始验证668Pay订单创建参数', {
      orderId: request.orderId,
      paymentMethod: request.paymentMethod,
      amount: request.amount
    });

    if (!request.paymentName || request.paymentName.trim() === '') {
      throw new AppError('付款人真实名称(paymentName)是必填项', ErrorCode.VALIDATION_ERROR, { orderId: request.orderId });
    }

    if (!request.transAccNo || request.transAccNo.trim() === '') {
      throw new AppError('银行卡号(transAccNo)是必填项', ErrorCode.VALIDATION_ERROR, {
        orderId: request.orderId,
        paymentMethod: request.paymentMethod
      });
    }

    // 验证银行卡号格式
    if (!/^\d{10,20}$/.test(request.transAccNo)) {
      throw new AppError('银行卡号格式不正确，应为10-20位数字', ErrorCode.VALIDATION_ERROR, {
        orderId: request.orderId,
        transAccNo: request.transAccNo?.substring(0, 4) + '****'
      });
    }

    if (!request.bankCode || request.bankCode.trim() === '') {
      throw new AppError('银行编码(bankCode)是必填项', ErrorCode.VALIDATION_ERROR, {
        orderId: request.orderId,
        paymentMethod: request.paymentMethod
      });
    }

    if (request.amount <= 0) {
      throw new AppError('充值金额必须大于0', ErrorCode.VALIDATION_ERROR, {
        orderId: request.orderId,
        amount: request.amount
      });
    }

    Logger.debug('668Pay订单创建参数验证通过', { orderId: request.orderId });
  }

  /**
   * 生成订单号
   */
  generateOrderId(): string {
    return `P668${Date.now()}${Math.random().toString(36).substring(2, 6).toUpperCase()}`;
  }

  /**
   * 获取支付类型编码
   */
  private getWayCode(paymentMethod: 'BankTransfer' | 'qrPay'): string {
    // 根据文档，泰国地区：
    // 网银转账：803
    // 二维码支付：804
    return paymentMethod === 'BankTransfer' ? '803' : '804';
  }

  /**
   * 创建提现订单
   */
  async createPayoutOrder(request: CreatePay668PayoutRequest): Promise<Pay668PayoutResponse> {
    // 参数验证
    this.validateCreatePayoutOrderRequest(request);

    // 668Pay代付金额单位是分，需要转换
    const amountInCents = Math.round(request.amount * 100);

    // 根据668Pay代付文档构建参数
    const params: any = {
      mchNo: this.config.mchNo,
      appId: this.config.appId,
      mchOrderNo: request.orderId,
      amount: amountInCents, // 转账金额（分）
      entryType: 'BANK_CARD', // 泰国使用BANK_CARD入账方式
      accountNo: request.receiverBankCard, // 收款账号（银行卡号）
      accountCode: request.bankCode, // 收款账号编码（银行编码）
      accountName: request.receiverName, // 收款人姓名
      accountEmail: request.customerEmail || 'system@example.com', // 收款人邮箱（必填）
      accountPhone: request.customerPhone || '+66000000000', // 收款人手机号（必填）
    };

    // 可选参数
    if (request.bankCode) {
      params.bankName = request.bankCode; // 银行名称或编码（泰国可选）
    }

    // 异步通知地址（可选）
    if (this.config.notifyUrl) {
      params.notifyUrl = this.config.notifyUrl;
    }

    // 扩展参数（可选）
    if (request.remark) {
      params.extParam = request.remark;
    }

    // 生成签名
    const sign = this.signWithMD5(params);
    params.sign = sign;

    Logger.info('668Pay代付订单请求参数', {
      mchOrderNo: params.mchOrderNo,
      amount: params.amount,
      entryType: params.entryType,
      accountName: params.accountName,
      accountNo: params.accountNo.substring(0, 4) + '****' // 脱敏处理
    });

    try {
      // 使用代付API地址
      const payoutApiUrl = 'https://pay.668pay.vip/api/payout/pay';
      
      const response = await fetch(payoutApiUrl, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(params),
      });

      if (!response.ok) {
        throw new AppError(`668Pay代付API HTTP错误: ${response.status}`, ErrorCode.PAYMENT_API_ERROR);
      }

      const responseText = await response.text();
      Logger.info('668Pay代付订单原始响应', { response: responseText });

      try {
        const result: Pay668PayoutResponse = JSON.parse(responseText);
        Logger.info('668Pay代付订单响应', result);

        return result;
      } catch (jsonError) {
        Logger.error('668Pay代付订单响应JSON解析失败', jsonError);
        throw new AppError(`668Pay代付响应格式错误: ${responseText}`, ErrorCode.PAYMENT_API_ERROR);
      }
    } catch (error) {
      Logger.error('668Pay代付订单请求失败', error);
      throw new AppError(
        `668Pay代付请求失败: ${error instanceof Error ? error.message : 'Unknown error'}`,
        ErrorCode.PAYMENT_API_ERROR
      );
    }
  }

  /**
   * 验证提现订单创建参数
   */
  private validateCreatePayoutOrderRequest(request: CreatePay668PayoutRequest): void {
    if (!request.receiverName || request.receiverName.trim() === '') {
      throw new AppError('收款人姓名(receiverName)是必填项', ErrorCode.VALIDATION_ERROR);
    }

    if (!request.receiverBankCard || request.receiverBankCard.trim() === '') {
      throw new AppError('收款银行卡号(receiverBankCard)是必填项', ErrorCode.VALIDATION_ERROR);
    }

    if (!request.bankCode || request.bankCode.trim() === '') {
      throw new AppError('银行编码(bankCode)是必填项', ErrorCode.VALIDATION_ERROR);
    }

    if (request.amount <= 0) {
      throw new AppError('提现金额必须大于0', ErrorCode.VALIDATION_ERROR);
    }

    // 验证金额精度（668Pay支持两位小数）
    if (!/^\d+(\.\d{1,2})?$/.test(request.amount.toString())) {
      throw new AppError('提现金额最多支持两位小数', ErrorCode.VALIDATION_ERROR);
    }

    Logger.debug('668Pay提现订单参数验证通过', { orderId: request.orderId });
  }

  /**
   * 创建充值订单
   */
  async createRechargeOrder(request: CreatePay668OrderRequest): Promise<Pay668Response> {
    // 参数验证
    this.validateCreateOrderRequest(request);

    // 668Pay金额单位是分，需要转换
    const amountInCents = Math.round(request.amount * 100);

    const params: any = {
      mchNo: this.config.mchNo,
      appId: this.config.appId,
      mchOrderNo: request.orderId,
      amount: amountInCents,
      customerName: request.paymentName,
      customerEmail: request.customerEmail || `${request.userId}@example.com`,
      customerPhone: request.customerPhone || '13800138000',
      //wayCode: this.getWayCode(request.paymentMethod),
      extParam: `${request.transAccNo}#${request.bankCode}`, // 泰国格式：卡号#编码
    };

    // 添加回调地址
    if (this.config.notifyUrl) {
      params.notifyUrl = this.config.notifyUrl;
    }

    // 添加透传参数
    if (request.extendParam) {
      params.extParam += `|${request.extendParam}`;
    }

    // 生成签名
    const sign = this.signWithMD5(params);
    const requestData = {
      ...params,
      sign,
    };

    Logger.info('668Pay创建订单请求', {
      orderId: request.orderId,
      mchNo: this.config.mchNo,
      mchOrderNo: requestData.mchOrderNo,
      amount: requestData.amount,
      //wayCode: requestData.wayCode,
      ustomerName: requestData.customerName
    });

    try {
      const response = await fetch(this.config.apiUrl, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(requestData),
      });

      Logger.debug('668Pay HTTP响应状态', {
        status: response.status,
        orderId: request.orderId
      });

      const responseText = await response.text();

      if (!response.ok) {
        Logger.error('668Pay创建订单HTTP错误', new Error(`HTTP ${response.status}`), {
          orderId: request.orderId,
          status: response.status,
          responseBody: responseText
        });
        throw new AppError(`668Pay API HTTP错误: ${response.status}`, ErrorCode.PAYMENT_API_ERROR, {
          orderId: request.orderId,
          status: response.status
        });
      }

      try {
        const result: Pay668Response = JSON.parse(responseText);

        Logger.info('668Pay创建订单响应', {
          orderId: request.orderId,
          code: result.code,
          response: result
        });

        return result;
      } catch (parseError) {
        Logger.error('668Pay创建订单响应解析失败', parseError, {
          orderId: request.orderId,
          responseText
        });
        throw new AppError(`668Pay响应解析失败: ${responseText}`, ErrorCode.PAYMENT_API_ERROR, {
          orderId: request.orderId
        });
      }
    } catch (error) {
      if (error instanceof AppError) {
        throw error;
      }

      Logger.error('668Pay创建订单请求失败', error, { orderId: request.orderId });
      throw new AppError(`668Pay API请求失败: ${error instanceof Error ? error.message : 'Unknown error'}`, ErrorCode.PAYMENT_API_ERROR, {
        orderId: request.orderId
      });
    }
  }

  /**
   * 验证异步通知
   */
  verifyNotification(notification: Pay668Notification): boolean {
    const { sign, ...params } = notification;
    return this.verifySignature(params, sign);
  }

  /**
   * 查询668Pay订单状态
   */
  async queryOrderStatus(request: QueryPay668OrderRequest): Promise<Pay668QueryResponse> {
    // 验证参数：payOrderId和mchOrderNo至少传一个
    if (!request.payOrderId && !request.mchOrderNo) {
      throw new AppError('payOrderId和mchOrderNo至少传一个', ErrorCode.VALIDATION_ERROR);
    }

    const params: any = {
      mchNo: this.config.mchNo,
      appId: this.config.appId,
    };

    // 添加订单号参数
    if (request.payOrderId) {
      params.payOrderId = request.payOrderId;
    }
    if (request.mchOrderNo) {
      params.mchOrderNo = request.mchOrderNo;
    }

    // 生成签名
    const sign = this.signWithMD5(params);
    const requestData = {
      ...params,
      sign,
    };

    Logger.info('668Pay查询订单请求', {
      mchNo: this.config.mchNo,
      payOrderId: request.payOrderId,
      mchOrderNo: request.mchOrderNo
    });

    try {
      // 使用查询API地址
      const queryApiUrl = this.config.apiUrl.replace('/api/pay/pay', '/api/pay/query');

      const response = await fetch(queryApiUrl, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(requestData),
      });

      Logger.debug('668Pay查询HTTP响应状态', {
        status: response.status,
        payOrderId: request.payOrderId,
        mchOrderNo: request.mchOrderNo
      });

      const responseText = await response.text();

      if (!response.ok) {
        Logger.error('668Pay查询订单HTTP错误', new Error(`HTTP ${response.status}`), {
          payOrderId: request.payOrderId,
          mchOrderNo: request.mchOrderNo,
          status: response.status,
          responseBody: responseText
        });
        throw new AppError(`668Pay查询API HTTP错误: ${response.status}`, ErrorCode.PAYMENT_API_ERROR, {
          payOrderId: request.payOrderId,
          mchOrderNo: request.mchOrderNo,
          status: response.status
        });
      }

      try {
        const result: Pay668QueryResponse = JSON.parse(responseText);

        Logger.info('668Pay查询订单响应', {
          payOrderId: request.payOrderId,
          mchOrderNo: request.mchOrderNo,
          code: result.code,
          state: result.data?.state,
          response: result
        });

        return result;
      } catch (parseError) {
        Logger.error('668Pay查询订单响应解析失败', parseError, {
          payOrderId: request.payOrderId,
          mchOrderNo: request.mchOrderNo,
          responseText
        });
        throw new AppError(`668Pay查询响应解析失败: ${responseText}`, ErrorCode.PAYMENT_API_ERROR, {
          payOrderId: request.payOrderId,
          mchOrderNo: request.mchOrderNo
        });
      }
    } catch (error) {
      if (error instanceof AppError) {
        throw error;
      }

      Logger.error('668Pay查询订单请求失败', error, {
        payOrderId: request.payOrderId,
        mchOrderNo: request.mchOrderNo
      });
      throw new AppError(`668Pay查询API请求失败: ${error instanceof Error ? error.message : 'Unknown error'}`, ErrorCode.PAYMENT_API_ERROR, {
        payOrderId: request.payOrderId,
        mchOrderNo: request.mchOrderNo
      });
    }
  }
}

// 创建668Pay服务实例
export function createPay668Service(): Pay668Service {
  const config: Pay668Config = {
    mchNo: process.env.PAY668_MCH_NO || '',
    appId: process.env.PAY668_APP_ID || '',
    apiKey: process.env.PAY668_API_KEY || '',
    apiUrl: process.env.PAY668_API_URL || 'https://pay.668pay.vip/api/pay/pay',
    notifyUrl: process.env.PAY668_NOTIFY_URL || '',
  };

  return new Pay668Service(config);
}

// 检查668Pay配置是否完整
export function isPay668Configured(): boolean {
  const mchNo = process.env.PAY668_MCH_NO;
  const appId = process.env.PAY668_APP_ID;
  const apiKey = process.env.PAY668_API_KEY;

  return !!(mchNo && appId && apiKey);
}
